package com.zenchn.controller;

import com.zenchn.annotation.OperLog;
import com.zenchn.entity.AreaTreeVO;
import com.zenchn.entity.HttpDataResult;
import com.zenchn.entity.LatLon;
import com.zenchn.entity.MenuVO;
import com.zenchn.enums.*;
import com.zenchn.exception.CustomException;
import com.zenchn.external.service.AmapService;
import com.zenchn.model.*;
import com.zenchn.service.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 通用的公共控制层
 *
 * @author dingxinfa
 * @date 2020-04-17
 */
@RestController
@RequestMapping(value = "common")
@Api(value = "通用模块接口", tags = "通用-公共接口")
@RequiresAuthentication
public class CommonController {

    private final String MODULE = "通用模块";

    @Resource
    private AuthorityService authorityService;

    @Resource
    private RoleAuthorityMapperService roleAuthorityMapperService;

    @Resource
    private AreasService areaService;

    @Resource
    private AmapService amapService;

    @Resource
    private AccountRoleMapperService accountRoleMapperService;

    @Resource
    private RegionService regionService;

    @Resource
    private AccountService accountService;

    @Resource
    private RegionDetailService regionDetailService;

    @Resource
    private AccountExtendService accountExtendService;

    /**
     * 获取登录账号角色相对应的菜单
     *
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @OperLog(module = MODULE, action = OperLogActionEnum.QUERY, detail = "获取登录账号角色相对应的菜单", isSaveRequestData = false)
    @ApiOperation(value = "获取登录账号角色相对应的菜单", notes = "获取登录账号角色相对应的菜单")
    @GetMapping(value = "/menuList")
    public ResponseEntity<HttpDataResult<List<MenuVO>>> menuList(HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpDataResult<List<MenuVO>> result = new HttpDataResult<>(request.getRequestURI());

        final TSysAccount currAccount = (TSysAccount) request.getSession().getAttribute(SessionAttributeEnum.CURRENT_ACCOUNT_INFO.getKey());

        TSysAccountRoleMapperExample accountRoleMapperExample = new TSysAccountRoleMapperExample();
        accountRoleMapperExample.createCriteria().andAccountIdEqualTo(currAccount.getAccountId());
        List<TSysAccountRoleMapper> accountRoleMapperList = accountRoleMapperService.selectByExample(accountRoleMapperExample);

        List<String> roleIds = accountRoleMapperList.stream().map(TSysAccountRoleMapper::getRoleId).collect(Collectors.toList());

        final List<TSysAuthority> authorityList = roleAuthorityMapperService.selectAuthorityByRoleIds(roleIds);


        List<String> authIdList = authorityList.stream().map(TSysAuthority::getAuthId).collect(Collectors.toList());

        List<MenuVO> menuVOList = authorityService.getMenuList(OauthClientEnum.SYSTEM_MANAGE_PLATFORM.getId(), authIdList);

        result.setData(menuVOList);

        result.setMessage("获取菜单列表成功.");
        result.setStatus(HttpStatus.OK.value());
        return new ResponseEntity<>(result, HttpStatus.OK);
    }


    /**
     * 获取通用状态列表
     *
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @OperLog(module = MODULE, action = OperLogActionEnum.QUERY, detail = "获取通用状态列表", isSaveRequestData = false)
    @ApiOperation(value = "获取通用状态列表", notes = "获取通用状态列表")
    @ApiImplicitParam(dataType = "String", name = "set", value = "集合{正常:normal;所有:all},默认 normal")
    @GetMapping(value = "/commonStatusList")
    public ResponseEntity<HttpDataResult<List<Map<String, Object>>>> commonStatusList(
            @RequestParam(required = false, value = "set", defaultValue = "normal") String set,
            HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpDataResult<List<Map<String, Object>>> result = new HttpDataResult<>(request.getRequestURI());

        if ("normal".equals(set.trim())) {
            result.setData(CommonStatusEnum.getNormalList());
        } else {
            result.setData(CommonStatusEnum.getAllList());
        }
        result.setMessage("获取通用状态列表成功.");
        result.setStatus(HttpStatus.OK.value());
        return new ResponseEntity<>(result, HttpStatus.OK);
    }

    /**
     * 获取地区经纬度
     *
     * @param areaCode
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @OperLog(module = MODULE, action = OperLogActionEnum.QUERY, detail = "获取地区经纬度")
    @ApiOperation(value = "获取地区经纬度", notes = "获取地区经纬度")
    @ApiImplicitParam(dataType = "String", name = "areaCode", value = "区域编码", required = true)
    @GetMapping(value = "/areaLatLng")
    public ResponseEntity<HttpDataResult<LatLon>> areaLatLng(
            @RequestParam(value = "areaCode") String areaCode,
            HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpDataResult<LatLon> result = new HttpDataResult<>(request.getRequestURI());

        TSysAreas areas = areaService.selectByPrimaryKey(areaCode);
        LatLon latLon = new LatLon();

        if (null == areas.getLongitude() || null == areas.getLatitude() || new BigDecimal(0).equals(areas.getLongitude()) || new BigDecimal(0).equals(areas.getLatitude())) {
            latLon = amapService.getLatLonByAddress(areas.getFullName());
            if (null != latLon) {
                areas.setLongitude(new BigDecimal(Double.toString(latLon.getLon())));
                areas.setLatitude(new BigDecimal(Double.toString(latLon.getLat())));
            }
            areaService.updateByPrimaryKey(areas);

        } else {
            latLon.setLat(areas.getLatitude().doubleValue());
            latLon.setLon(areas.getLongitude().doubleValue());
        }

        result.setData(latLon);
        result.setMessage("OK");
        result.setStatus(HttpStatus.OK.value());
        return new ResponseEntity<>(result, HttpStatus.OK);

    }

    /**
     * 获取区域级联数据
     *
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @OperLog(module = MODULE, action = OperLogActionEnum.QUERY, detail = "获取区域级联数据")
    @ApiOperation(value = "获取区域级联数据", notes = "获取区域级联数据")
    @ApiImplicitParam(dataType = "String", name = "areaCode", value = "区域编码")
    @GetMapping(value = "/getAreaTree")
    public ResponseEntity<HttpDataResult<List<AreaTreeVO>>> getAreaTree(
            @RequestParam(required = false, value = "areaCode") String areaCode,
            HttpServletRequest request, HttpServletResponse response) throws Exception {

        HttpDataResult<List<AreaTreeVO>> result = new HttpDataResult<>(request.getRequestURI());

        result.setData(areaService.getAreaTreebyAreaCodeAndIsEnable(areaCode));

        result.setMessage("获取组织机构控制的区域级联数据成功.");
        result.setStatus(HttpStatus.OK.value());
        return new ResponseEntity<>(result, HttpStatus.OK);
    }


    /***
     * 获取当前登入账户的扩展信息内容
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @OperLog(module = MODULE, action = OperLogActionEnum.QUERY, detail = "获取当前登入账户的扩展信息内容")
    @ApiOperation(value = "获取当前登入账户的扩展信息内容", notes = "获取当前登入账户的扩展信息内容")
    @GetMapping(value = "/projectList")
    public ResponseEntity<HttpDataResult<TMiAccountExtend>> projectList(
            HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpDataResult<TMiAccountExtend> result = new HttpDataResult<>(request.getRequestURI());

        TMiAccountExtend accountExtend = (TMiAccountExtend) request.getSession().getAttribute(SessionAttributeEnum.CURRENT_ACCOUNT_EXTEND_INFO.getKey());

        result.setData(accountExtend);
        result.setMessage("OK");
        result.setStatus(HttpStatus.OK.value());
        return new ResponseEntity<>(result, HttpStatus.OK);
    }

    /***
     * 获取所属省份列表
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @OperLog(module = MODULE, action = OperLogActionEnum.QUERY, detail = "获取所属省份列表")
    @ApiOperation(value = "获取所属省份列表", notes = "获取所属省份列表")
    @GetMapping(value = "/areasCodeList")
    public ResponseEntity<HttpDataResult<List<TSysAreas>>> areasCodeList(
            HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpDataResult<List<TSysAreas>> result = new HttpDataResult<>(request.getRequestURI());

        final TMiAccountExtend accountExtend = (TMiAccountExtend) request.getSession().getAttribute(SessionAttributeEnum.CURRENT_ACCOUNT_EXTEND_INFO.getKey());

        List<TSysAreas> areasList = new ArrayList<>();
        if (accountExtend != null) {
            //获取当前登入用户所属省份数据权限
            List<String> areasCodeList = new ArrayList<>();
            if (accountExtend.getRegionCode() != null && !"".equals(accountExtend.getRegionCode().trim())) {
                areasCodeList = getAreasCodeList(accountExtend.getRegionCode().trim());
            }
            if (accountExtend.getAreasCode() != null && !"".equals(accountExtend.getAreasCode().trim()) && !areasCodeList.contains(accountExtend.getAreasCode().trim())) {
                areasCodeList.add(accountExtend.getAreasCode().trim());
            }
            if (areasCodeList != null && !areasCodeList.isEmpty()) {
                TSysAreasExample areasExample = new TSysAreasExample();
                areasExample.createCriteria().andGradeEqualTo("1").andIsEnableEqualTo(true).andCodeIn(areasCodeList);

                areasList = areaService.selectByExample(areasExample);
            }
        }

        result.setData(areasList);
        result.setMessage("OK");
        result.setStatus(HttpStatus.OK.value());
        return new ResponseEntity<>(result, HttpStatus.OK);
    }

    /***
     * 获取所属区域列表
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @OperLog(module = MODULE, action = OperLogActionEnum.QUERY, detail = "获取所属区域列表")
    @ApiOperation(value = "获取所属区域列表", notes = "获取所属区域列表")
    @GetMapping(value = "/regionCodeList")
    public ResponseEntity<HttpDataResult<List<TMiRegion>>> regionCodeList(
            HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpDataResult<List<TMiRegion>> result = new HttpDataResult<>(request.getRequestURI());

        final TMiAccountExtend accountExtend = (TMiAccountExtend) request.getSession().getAttribute(SessionAttributeEnum.CURRENT_ACCOUNT_EXTEND_INFO.getKey());

        List<TMiRegion> regionList = new ArrayList<>();
        if (accountExtend != null && accountExtend.getRegionCode() != null && !"".equals(accountExtend.getRegionCode().trim())) {
            if (RegionEnum.NATIONAL_ADMINISTRATIVE_REGION.getId().equals(accountExtend.getRegionCode().trim())) {
                TMiRegionExample regionExample = new TMiRegionExample();
                regionList = regionService.selectByExample(regionExample);
            } else {
                TMiRegion region = regionService.selectByPrimaryKey(accountExtend.getRegionCode().trim());
                regionList.add(region);
            }
        }

        result.setData(regionList);
        result.setMessage("OK");
        result.setStatus(HttpStatus.OK.value());
        return new ResponseEntity<>(result, HttpStatus.OK);
    }

    /***
     * 获取用户列表
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @OperLog(module = MODULE, action = OperLogActionEnum.QUERY, detail = "获取用户列表")
    @ApiOperation(value = "获取用户列表", notes = "获取用户列表")
    @GetMapping(value = "/accountList")
    public ResponseEntity<HttpDataResult<List<TSysAccount>>> accountList(
            HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpDataResult<List<TSysAccount>> result = new HttpDataResult<>(request.getRequestURI());

        final TMiAccountExtend accountExtend = (TMiAccountExtend) request.getSession().getAttribute(SessionAttributeEnum.CURRENT_ACCOUNT_EXTEND_INFO.getKey());

        List<TSysAccount> accountList = new ArrayList<>();
        if (accountExtend != null) {
            //获取当前登入用户所属省份数据权限
            List<String> accountIdList = new ArrayList<>();
            List<String> areasCodeList = new ArrayList<>();
            if (accountExtend.getRegionCode() != null && !"".equals(accountExtend.getRegionCode().trim())) {
                if (RegionEnum.NATIONAL_ADMINISTRATIVE_REGION.getId().equals(accountExtend.getRegionCode().trim())) {
                    TMiAccountExtendExample accountExtendExample = new TMiAccountExtendExample();
                    accountIdList.addAll(accountExtendService.selectByExample(accountExtendExample).stream().map(TMiAccountExtend::getAccountId).collect(Collectors.toList()));
                }else {
                    TMiAccountExtendExample accountExtendExample = new TMiAccountExtendExample();
                    accountExtendExample.createCriteria().andRegionCodeEqualTo(accountExtend.getRegionCode().trim());

                    accountIdList.addAll(accountExtendService.selectByExample(accountExtendExample).stream().map(TMiAccountExtend::getAccountId).collect(Collectors.toList()));

                    areasCodeList = getAreasCodeList(accountExtend.getRegionCode().trim());
                }
            }
            if (accountExtend.getAreasCode() != null && !"".equals(accountExtend.getAreasCode().trim()) && !areasCodeList.contains(accountExtend.getAreasCode())) {
                areasCodeList.add(accountExtend.getAreasCode().trim());
            }
            if (areasCodeList != null && !areasCodeList.isEmpty()) {
                TMiAccountExtendExample accountExtendExample = new TMiAccountExtendExample();
                accountExtendExample.createCriteria().andAreasCodeIn(areasCodeList);

                accountIdList.addAll(accountExtendService.selectByExample(accountExtendExample).stream().map(TMiAccountExtend::getAccountId).collect(Collectors.toList()));
            }
            if (accountIdList != null && !accountIdList.isEmpty()) {
                TSysAccountExample accountExample = new TSysAccountExample();
                accountExample.createCriteria().andStatusNotEqualTo(CommonStatusEnum.DELETE.getCode()).andAccountIdIn(accountIdList.stream().distinct().collect(Collectors.toList()));

                accountList = accountService.selectByExample(accountExample);
            }
        }

        result.setData(accountList);
        result.setMessage("OK");
        result.setStatus(HttpStatus.OK.value());
        return new ResponseEntity<>(result, HttpStatus.OK);
    }

    /**
     * 获取省份信息
     *
     * @param regionId
     * @return
     */
    private List<String> getAreasCodeList(String regionId) {
        List<String> areasCodeList = new ArrayList<>();
        TMiRegionDetailExample regionDetailExample = new TMiRegionDetailExample();
        regionDetailExample.createCriteria().andRegionIdEqualTo(regionId);

        List<TMiRegionDetail> regionDetailList = regionDetailService.selectByExample(regionDetailExample);
        if (regionDetailList != null && !regionDetailList.isEmpty()) {
            areasCodeList.addAll(regionDetailList.stream().map(TMiRegionDetail::getAreasCode).collect(Collectors.toList()));
        }
        return areasCodeList;
    }
}
